import typing

import numpy as np


def triangle2base(point_list: typing.Union[list, tuple]):
    v0 = (point_list[1][0] - point_list[0][0], point_list[1][1] - point_list[0][1])
    v1 = (point_list[2][0] - point_list[0][0], point_list[2][1] - point_list[0][1])
    return v0, v1


def transform_vector(origin: tuple, current: tuple, target: tuple) -> tuple:
    """
    current向量是由origin向量变换而来，需要计算经过相同变换后的target向量。
    该变换由旋转和缩放构成，旋转角度由两个向量的夹角确定，缩放比例由两个向量的长度比值确定。
    输入输出均为二维向量。
    :param origin:
    :param current:
    :param target:
    :return:
    """
    origin = np.array(origin)
    current = np.array(current)
    target = np.array(target)
    # 计算current与origin的长度比值
    s = np.linalg.norm(current) / np.linalg.norm(origin)
    # 计算旋转角度
    sin_theta = (-current[0] * origin[1] + current[1] * origin[0]) / (np.linalg.norm(current) * np.linalg.norm(origin))
    cos_theta = (current[0] * origin[0] + current[1] * origin[1]) / (np.linalg.norm(current) * np.linalg.norm(origin))
    # 计算变换矩阵
    T = np.array([[cos_theta, -sin_theta], [sin_theta, cos_theta]]) * s
    # 计算变换后的向量
    new_target = np.dot(T, target)
    return tuple(new_target)


# def transform_base(a1: tuple, a2: tuple, b1: tuple, b2: tuple, point: tuple) -> tuple:
#     """
#     a1, a2是一组基向量，b1, b2是另一组基向量，point是需要变换的点。
#     计算point在a1, a2基向量下对应的坐标，计算该坐标在b1, b2基向量下对应的坐标。
#     输入输出均为二维向量。
#     :param a1:
#     :param a2:
#     :param b1:
#     :param b2:
#     :param point:
#     :return:
#     """
#     a1 = np.array(a1)
#     a2 = np.array(a2)
#     b1 = np.array(b1)
#     b2 = np.array(b2)
#     point = np.array(point)
#     # 计算a1, a2基向量在原点的坐标
#     a1_coord = np.dot(a1, point) / pow(np.linalg.norm(a1), 2)
#     a2_coord = np.dot(a2, point) / pow(np.linalg.norm(a2), 2)
#     # 同等比例，在b1, b2基向量下对应的坐标
#     return tuple([float(x) for x in a1_coord * b1 + a2_coord * b2])


def transform_base(triangle1, triangle2, point: tuple) -> tuple:
    origin1 = triangle1[0]
    origin2 = triangle2[0]
    base1_1, base1_2 = triangle2base(triangle1)
    base2_1, base2_2 = triangle2base(triangle2)

    a1 = np.array(base1_1)
    a2 = np.array(base1_2)
    b1 = np.array(base2_1)
    b2 = np.array(base2_2)
    point = np.array(point)
    origin1 = np.array(origin1)
    origin2 = np.array(origin2)

    # 计算a1, a2基向量在origin1的坐标
    M = np.column_stack((a1, a2))
    if np.linalg.det(M) == 0:
        # 矩阵不可逆
        print("WARNING: Matrix is singular")
        return tuple([float(x) for x in origin2])
    M_inv = np.linalg.inv(M)
    a1_coord, a2_coord = M_inv @ (point - origin1)

    # 同等比例，在b1, b2基向量下对应的坐标
    res = a1_coord * b1 + a2_coord * b2 + origin2
    return tuple([float(x) for x in res])


def test_transform_vector():
    origin = (1, 0)
    current = (1, 1)
    target = (1, 1)
    result = transform_vector(origin, current, target)
    # assert result == (1, 1, 1)
    print(result)


def test_transform_base():
    a1 = (1, 0)
    a2 = (0, 1)
    b1 = (1, 1)
    b2 = (1, -1)
    point = (1, 1)
    result = transform_base(a1, a2, b1, b2, point)
    # assert result == (2, 0)
    print(result)


if __name__ == '__main__':
    # test_transform_vector()
    test_transform_base()
